/* 
 * File:   EvolutionOfMorphologyAndBehavior.h
 * Author: jcrada
 *
 * Created on April 14, 2009, 2:25 AM
 */

#ifndef _EVOLUTIONOFMORPHOLOGYANDBEHAVIOR_H
#define	_EVOLUTIONOFMORPHOLOGYANDBEHAVIOR_H

#include "EvolutionOfCreatures.h"
#include "PsoModel.h"
#include "BodyPart.h"
#include "TreeOfNodes.h"

namespace jcrada {

    class EvolutionOfMorphologyAndBehavior : public EvolutionOfCreatures {
    private:
        PsoModel* _pso;
        int _number_of_morphologies;
        TreeOfNodes** _morphologies;
        int* _creatures_morphology_index;
        int _body_parts;
        int _hidden_layers;
        int _neurons_per_layer;
        int _max_iterations;
        double _min_size;
        double _max_size;
        double _min_mass;
        double _max_mass;

    protected:
        virtual void setupPsoModel();
        virtual void setupCreatures();

        virtual BodyPart::eShape getShape(double value);
        virtual void setup(Creature& creature, const TreeOfNodes& morphology);

        virtual void setNumberOfMorphologies(int morphs){
            this->_number_of_morphologies = morphs;
        }

        virtual void setMorphology(int index, TreeOfNodes* morphology) {
            this->_morphologies[index] = morphology;
        }

        virtual void setCreaturesMorphologyIndex(int creature_index, int morphology_index) {
            this->_creatures_morphology_index[creature_index] = morphology_index;
        }


    public:

        EvolutionOfMorphologyAndBehavior(int population_size, int body_parts,
                int hidden_layers, int neurons_per_layer, int max_iterations,
                double min_size, double max_size,
                double min_mass, double max_mass);

        virtual ~EvolutionOfMorphologyAndBehavior();

        virtual void step();
        virtual void prepareCreatures();

        virtual PsoModel& getPsoModel() const {
            return *this->_pso;
        }

        virtual TreeOfNodes& getMorphology(int index) {
            assert(index >= 0 && index < getNumberOfMorphologies());
            return *this->_morphologies[index];
        }

        virtual int getNumberOfMorphologies() const {
            return this->_number_of_morphologies;
        }

        virtual int getMorphologyIndex(const Creature& creature) const {
            for (int i = 0; i < getPopulationSize(); ++i) {
                if (&creature == &getCreature(i)) {
                    return _creatures_morphology_index[i];
                }
            }
            return -1;
        }

        virtual int getMorphologyIndex(int creature_index) const{
            assert(creature_index >= 0 && creature_index < getPopulationSize());
            return _creatures_morphology_index[creature_index];
        }

        virtual int getBodyParts() const {
            return this->_body_parts;
        }

        virtual int getHiddenLayers() const {
            return this->_hidden_layers;
        }

        virtual int getNeuronsPerLayer() const {
            return this->_neurons_per_layer;
        }

        virtual double getMinSize() const {
            return this->_min_size;
        }

        virtual double getMinMass() const {
            return this->_min_mass;
        }

        virtual double getMaxSize() const {
            return this->_max_size;
        }

        virtual double getMaxMass() const {
            return this->_max_mass;
        }

        virtual int getMaxIterations() const{
            return this->_max_iterations;
        }

    };
}

#endif	/* _EVOLUTIONOFMORPHOLOGYANDBEHAVIOR_H */

